#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "whisper.h"
#include "common-whisper.h"

#include <cstdio>
#include <cfloat>
#include <string>
#include <cstring>

#ifdef NDEBUG
#undef NDEBUG
#endif

#include <cassert>

#include <QMainWindow>
#include <QAudioRecorder>
#include <QAudioProbe>
#include <QUrl>
#include <QFileDialog>

class AudioRecorderWithProbe : public QObject
{
    Q_OBJECT

public:
    AudioRecorderWithProbe(QObject *parent = nullptr) : QObject(parent)
    {
        audioRecorder = new QAudioRecorder(this);

        // 创建音频探针
        audioProbe = new QAudioProbe(this);

        // 连接音频缓冲区信号
        connect(audioProbe, &QAudioProbe::audioBufferProbed,
                this, &AudioRecorderWithProbe::processBuffer);

        // 设置探针到录音器
        if (!audioProbe->setSource(audioRecorder)) {
            qWarning() << "Failed to set audio probe";
        }
        audioRecorder->setAudioInput(audioRecorder->defaultAudioInput());
        // 设置录音参数
        QAudioEncoderSettings settings;
        settings.setCodec("audio/pcm");
        settings.setSampleRate(16000);
        settings.setChannelCount(1);
        settings.setQuality(QMultimedia::HighQuality);
        settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);

        audioRecorder->setEncodingSettings(settings);

    }

    void setFile()
    {
        auto file = QFileDialog::getSaveFileName(nullptr,"");
        audioRecorder->setOutputLocation(QUrl::fromLocalFile(file));
    }

    void startRecording()
    {
        audiodata.clear();
        audioRecorder->record();
    }

    void stop()
    {
        audioRecorder->stop();
    }
    QByteArray audiodata;

private slots:
    void processBuffer(const QAudioBuffer &buffer)
    {
        // 实时处理音频缓冲区
        qDebug() << "Buffer format:" << buffer.format();
        qDebug() << "Buffer sample count:" << buffer.sampleCount();
        qDebug() << "Buffer duration:" << buffer.duration() / 1000.0 << "ms";

        // 转换为字节数组处理
        QByteArray audioData = bufferToByteArray(buffer);
        emit audioDataProcessed(audioData);
        audiodata.append(audioData);
    }

private:
    QByteArray bufferToByteArray(const QAudioBuffer &buffer)
    {
        QByteArray data;
        const char *ptr = reinterpret_cast<const char*>(buffer.constData());
        int size = buffer.byteCount();
        data.append(ptr, size);
        return data;
    }

signals:
    void audioDataProcessed(const QByteArray &data);

private:
    QAudioRecorder *audioRecorder;
    QAudioProbe *audioProbe;
};

#include <QAudioInput>
#include <QByteArray>
#include <QComboBox>
#include <QMainWindow>
#include <QObject>
#include <QPixmap>
#include <QPushButton>
#include <QSlider>
#include <QWidget>
#include <QScopedPointer>
#include <QBuffer>

class AudioInfo : public QIODevice
{
    Q_OBJECT

public:
    AudioInfo(const QAudioFormat &format);

    void start();
    void stop();

    qreal level() const { return m_level; }

    qint64 readData(char *data, qint64 maxlen) override;
    qint64 writeData(const char *data, qint64 len) override;

    QByteArray array;

private:
    const QAudioFormat m_format;
    quint32 m_maxAmplitude = 0;
    qreal m_level = 0.0; // 0.0 <= m_level <= 1.0

signals:
    void update();
};


QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void recognition(std::vector<float> pcmf32);

    void initializeAudio(const QAudioDeviceInfo &deviceInfo);

    void toggleMode();

    void stopRecording();

private:
    Ui::MainWindow *ui;
    AudioRecorderWithProbe *m_pAudioRecorderWithProbe = nullptr;
    struct whisper_context * wctx;

    QScopedPointer<AudioInfo> m_audioInfo;
    QScopedPointer<QAudioInput> m_audioInput;

    QByteArray audioData;
    QBuffer buffer;
};

#endif // MAINWINDOW_H
